package esb.chapter9.restaurant.routing.camel;

import java.io.StringReader;
import java.util.Calendar;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;

import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.camel.Processor;
import org.apache.servicemix.jbi.jaxp.StringSource;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

import esb.chapter9.restaurant.routing.camel.xfire.XsDateTimeFormat;
import esb.chapter9.restaurant.routing.dao.ReservationDAOIF;
import esb.chapter9.restaurant.routing.model.Reservation;

public class ExpirationProcessor implements Processor {
	
	public void process(Exchange exchange) throws Exception {
		StringSource payload =  (StringSource) exchange.getIn().getBody();
		ReservationDAOIF reservationDAO = exchange.getContext().getRegistry().lookup("restaurantDAO", ReservationDAOIF.class);
		Reservation reservation = createReservation(payload);
		reservation = reservationDAO.saveReservation(reservation);
		String responsePayload = addReservationID(payload.getText(), reservation.getReservationID());
		Message responseMessage = exchange.getOut();
		responseMessage.setBody(new StringSource(responsePayload));
    }
	
	private Reservation createReservation(StringSource payload) throws Exception {
		Reservation reservation = new Reservation();
	    XPath xpath = XPathFactory.newInstance().newXPath();
	    NSContext ctx = new NSContext();
	    ctx.setNamespace("esb", "http://message.service.restaurant.chapter9.esb");
	    ctx.setNamespace("res", "http://esbinaction.com/restaurant");
	    xpath.setNamespaceContext(ctx);
	    InputSource payloadSource = new InputSource(new StringReader(payload.getText()));
	    Node startNode = (Node) xpath.compile("//res:out").evaluate(payloadSource, XPathConstants.NODE);
	    reservation.setRestaurantName(executeXPath(xpath.compile("//esb:restaurant"), startNode));
	    reservation.setGuestName(executeXPath(xpath.compile("//esb:guestName"), startNode));
	    reservation.setNumberOfPersons(Integer.valueOf(executeXPath(xpath.compile("//esb:persons"), startNode)));
	    reservation.setRoomNumber(Integer.valueOf(executeXPath(xpath.compile("//esb:roomNumber"), startNode)));
	    XsDateTimeFormat format = new XsDateTimeFormat();
	    Calendar reservationCal = (Calendar) format.parseObject(executeXPath(xpath.compile("//esb:reservationTime"), startNode));
	    reservation.setReservationTime(reservationCal.getTime());
	    return reservation;
	}
	
	private String executeXPath(XPathExpression pathExpr, Node startNode) throws Exception {
		Node xpathNode = (Node) pathExpr.evaluate(startNode, XPathConstants.NODE);
	    return xpathNode.getTextContent();
	}
	
	private String addReservationID(String payload, long reservationID) {
		System.out.println("payload " + payload);
		StringBuffer payloadBuffer = new StringBuffer(payload);
		int outIndex = payloadBuffer.indexOf("<out");
		payloadBuffer.replace(outIndex, outIndex + 4, "<out reservationID=\"" + reservationID + "\"");
		return payloadBuffer.toString();
	}

}
